package main

import (
	"fmt"
	"reflect"
	"unsafe"
)

func main() {
	bytes := make([]byte, 0, 20)
	bytes = append(bytes, '1','2','3','4','5')

	ss := bytesToString(bytes) // 直接用 []byte 构建 string
	fmt.Println(ss,string(bytes)) // 12345 12345

	// 修改切片某一项，字符串也会改变
	{
		bytes[3] = 'a'
		fmt.Println(ss,string(bytes))            // 123a5 123a5
		bytes = append(bytes, 'b')
		fmt.Println(ss,string(bytes)) // 123a5 123a5b  todo 如果不改变字符串长度，字符串取不到更多的值
		// 单纯追加无效，应该同时修改字符串的长度
		((*reflect.StringHeader)(unsafe.Pointer(&ss))).Len++
		fmt.Println(ss,string(bytes)) // 123a5b 123a5b
	}
	// todo 果然 unsafe 不安全，用这种方法构建的字符串，可以通过修改底层数组来修改字符串的值
	// todo 这也是一个妙用，可以用该数据来控制字符串
	// todo 如果切片发生了扩容，切片底层的数据地址就变了，就控制不到了
}

func bytesToString(bs []byte) string {
	// 直接用[]byte作为string底层的数组
	return *(*string)(unsafe.Pointer(&bs))
}

